/********************************************************************************
 * Copyright (c) 2011-2017 Red Hat Inc. and/or its affiliates and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 1.0 which is available at
 * http://www.eclipse.org/legal/epl-v10.html.
 *
 * SPDX-License-Identifier: EPL-1.0
 ********************************************************************************/
package org.eclipse.ceylon.ide.eclipse.code.editor;

import static org.eclipse.ceylon.ide.eclipse.code.editor.RefinementAnnotationCreator.TODO_ANNOTATION_TYPE;
import static org.eclipse.ceylon.ide.eclipse.code.editor.CeylonAnnotation.isParseAnnotation;
import static org.eclipse.ceylon.ide.eclipse.code.parse.TreeLifecycleListener.Stage.TYPE_ANALYSIS;
import static org.eclipse.ceylon.ide.eclipse.core.builder.CeylonBuilder.PROBLEM_MARKER_ID;
import static org.eclipse.ceylon.ide.eclipse.core.builder.CeylonBuilder.TASK_MARKER_ID;

import java.util.Iterator;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.texteditor.MarkerAnnotation;

import org.eclipse.ceylon.ide.eclipse.code.parse.CeylonParseController;
import org.eclipse.ceylon.ide.eclipse.code.parse.TreeLifecycleListener;

class MarkerAnnotationUpdater implements TreeLifecycleListener {
    
    private CeylonEditor editor;
    
    public MarkerAnnotationUpdater(CeylonEditor editor) {
        this.editor = editor;
    }
    
    public Stage getStage() {
        return TYPE_ANALYSIS;
    }
    
    /**
     * Remove any Marker annotations that don't correspond 
     * to existing problems according to the most recent 
     * tree / typecheck
     */
    public void update(CeylonParseController parseController, 
            IProgressMonitor monitor) {
        if (editor.isBackgroundParsingPaused() || 
                monitor.isCanceled()) {
            return;
        }
        
        if (parseController.getStage().ordinal() 
                >= getStage().ordinal()) {
            IAnnotationModel model = 
                    editor.getDocumentProvider()
                        .getAnnotationModel(
                                editor.getEditorInput());
            for (Iterator<Annotation> iter = 
                        model.getAnnotationIterator(); 
                    iter.hasNext();) {
                Annotation ann = iter.next();
                if (ann instanceof MarkerAnnotation) {
                    MarkerAnnotation ma = 
                            (MarkerAnnotation) ann;
                    IMarker marker = ma.getMarker();
                    try {
                        String type = marker.getType();
                        boolean isProblemMarker = 
                                type.equals(PROBLEM_MARKER_ID);
//                        boolean isModuleDependencyMarker = 
//                                type.equals(MODULE_DEPENDENCY_PROBLEM_MARKER_ID);
                        boolean isTaskMarker = 
                                type.equals(TASK_MARKER_ID);
                        
                        Integer markerStart = 
                                (Integer) 
                                    marker.getAttribute(
                                        IMarker.CHAR_START);
                        Integer markerEnd = 
                                (Integer) 
                                    marker.getAttribute(
                                        IMarker.CHAR_END);
                        if (markerStart==null || markerEnd==null) {
                            continue;
                        }
                        
                        if (isProblemMarker //&& !isModuleDependencyMarker 
                                || isTaskMarker) {
                            boolean found = false;
                            for (Iterator<Annotation> iter2 = 
                                        model.getAnnotationIterator(); 
                                    iter2.hasNext();) {
                                Annotation ann2 = iter2.next();
                                boolean problem = 
                                        isProblemMarker && 
                                        isParseAnnotation(ann2);
                                boolean task = 
                                        isTaskMarker && 
                                        isTodoAnnotation(ann2);
                                if (problem || task) {
                                    Position position = 
                                            model.getPosition(ann2);
                                    if (markerStart.intValue()
                                            == position.offset &&
                                        markerEnd.intValue()
                                            == position.offset
                                             + position.length) {
                                        found=true;
                                        break;
                                    }
                                }
                            }
                            if (!found) {
                                model.removeAnnotation(ann);
                            }
                        }
                    }
                    catch (CoreException e) {
                        model.removeAnnotation(ann);
                    }
                }
            }
        }
    }

    private static boolean isTodoAnnotation(Annotation ann) {
        return ann.getType().equals(TODO_ANNOTATION_TYPE);
    }
}